package com.night.card.service.impl;


import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.night.card.exception.LessMoneyException;
import com.night.card.mapper.CardInMapper;
import com.night.card.mapper.CardMapper;
import com.night.card.mapper.CardOutMapper;
import com.night.card.service.interfs.CardService;
import com.night.common.entity.card.Card;
import com.night.common.entity.card.CardIn;
import com.night.common.entity.card.CardOut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: CardServiceImp
 * @Description: CardService实现类
 * @author: CHX42
 * @date: 2022/10/20-22:05
 * @version: v1.0
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CardServiceImp implements CardService {
    @Value("${ss.card.pageSize}")
    private int pageSize;
    @Resource
    private CardMapper cardMapper;
    @Resource
    private CardInMapper cardInMapper;
    @Resource
    private CardOutMapper cardOutMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void add(Card card) {
        cardMapper.insert(card);
    }

    @Override
    public void delete(Integer id) {
        cardMapper.delete(id);
    }

    @Override
    public Card getById(Integer id) {
        //先从redis查询是否有数据
        Card redisCard = (Card) redisTemplate.opsForValue().get("card_" + id);
        if (redisCard != null)
            return redisCard;
        //不存在，再从数据库中查询
        Card card = cardMapper.selectById(id);
        //将数据存入Redis缓存
        redisTemplate.opsForValue().set("card_" + card.getId(), card, 30, TimeUnit.SECONDS);
        return card;
    }

    @Override
    public PageInfo<Card> getAll() {
        PageHelper.startPage(1, Integer.MAX_VALUE);
        List<Card> redisCardList = (List<Card>) redisTemplate.opsForValue().get("card_all");
        if (redisCardList != null)
            return new PageInfo<>(redisCardList);
        //开始分页，默认分页大小为10
        PageHelper.startPage(1, Integer.MAX_VALUE);
        List<Card> cardList = cardMapper.select(new Card());
        redisTemplate.opsForValue().set("card_all", cardList, 30, TimeUnit.SECONDS);
        //包装数据为pageInfo返回
        return new PageInfo<>(cardList);
    }

    @Override
    public PageInfo<Card> getBy(PageInfo<Card> pageInfo) {
        String pageName = "card_list_pageNum_" + pageInfo.getPageNum() + "_pageSize_" + pageInfo.getPageSize();
        Card card;//查询条件Card
        if (pageInfo.getList() != null && (card = pageInfo.getList().get(0)) != null) {
            //设计放入redis的键
            String cardNum = card.getCardNum();
            String name = card.getStudent().getName();
            String studentNumber = card.getStudent().getStudentNumber();
            String status = card.getCardStatus();
            if (cardNum != null && !"".equals(cardNum)) {
                pageName = pageName + "_carNum_" + cardNum;
            }
            if (name != null && !"".equals(name)) {
                pageName = pageName + "_name_" + name;
            }
            if (studentNumber != null && !"".equals(studentNumber)) {
                pageName = pageName + "_studentNumber_" + studentNumber;
            }
            if (status != null && !"".equals(status)) {
                pageName = pageName + "_cardStatus_" + status;
            }
        }
        PageHelper.startPage(1, pageInfo.getPageSize());
        PageInfo<Card> redisCardPageInfo = (PageInfo<Card>) redisTemplate.opsForValue().get(pageName);
        if (redisCardPageInfo != null)
            return redisCardPageInfo;
        //开始分页，默认分页大小为10
        PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        List<Card> cardList = cardMapper.select(pageInfo.getList().get(0));
        PageInfo<Card> cardPageInfo = new PageInfo<>(cardList);
        redisTemplate.opsForValue().set(pageName, cardPageInfo, 30, TimeUnit.SECONDS);
        //包装数据为pageInfo返回
        return cardPageInfo;
    }


    @Override
    public void update(Card card) {
        cardMapper.update(card);
        Card newCard = cardMapper.selectById(card.getId());
        //将数据存入Redis缓存
        redisTemplate.opsForValue().set("card_" + card.getId(), newCard, 30, TimeUnit.SECONDS);
    }

    @Override
    public void inMoney(CardIn cardIn) {
        //增加余额
        BigDecimal inMoney = cardIn.getInMoney();
        Integer cardId = cardIn.getCard().getId();
        Card card = new Card();
        card.setId(cardId);
        BigDecimal cardMoney = cardMapper.selectById(cardId).getCardMoney();
        card.setCardMoney(cardMoney.add(inMoney));
        cardMapper.update(card);
        //增加一条充值记录
        CardIn cardInTemp = new CardIn();
        cardInTemp.setCardId(cardId);
        cardInTemp.setInMoney(inMoney);
        cardInTemp.setInTime(DateUtil.now());
        cardInTemp.setInMachineId(cardIn.getInMachineId());
        cardInMapper.insert(cardInTemp);
    }

    @Override
    public void outMoney(CardOut cardOut) {
        //减少余额
        BigDecimal outMoney = cardOut.getOutMoney();
        Integer cardId = cardOut.getCardId();
        Card card = new Card();
        card.setId(cardId);
        BigDecimal cardMoney = cardMapper.selectById(cardId).getCardMoney();
        if (cardMoney.compareTo(outMoney) < 0)
            throw new LessMoneyException("余额不足");
        card.setCardMoney(cardMoney.subtract(outMoney));
        cardMapper.update(card);
        //增加一条消费记录
        CardOut cardOutTemp = new CardOut();
        cardOutTemp.setCardId(cardId);
        cardOutTemp.setOutMoney(outMoney);
        cardOutTemp.setOutTime(DateUtil.now());
        cardOutTemp.setOutMachineId(cardOut.getOutMachineId());
        cardOutMapper.insert(cardOutTemp);
    }

    @Override
    public Card getByStudentId(Integer studentId ) {
        return cardMapper.selectByStudentId(studentId);
    }

}
